#include "stage.h"
#include "RobotBase.h"

#ifndef __ROBOTANTIENTROPY_H__
#define __ROBOTANTIENTROPY_H__

using namespace Stg;
using namespace std;

#ifndef __MESSAGE__
#define __MESSAGE__
enum MessageType { BroadcastMessage, ExchangeMessage, AckMessage };

typedef struct NeighborNode_s {
    int lastUpdate;
    int neighborId;
    float historyEntropy;
    int session;
    float lastEntropy;
}NeighborNode;

class WifiMessageEntropy : public WifiMessageBase
{
    public: 
        WifiMessageEntropy():WifiMessageBase(){};
        ~WifiMessageEntropy(){ };

        WifiMessageEntropy(const WifiMessageEntropy& toCopy) : WifiMessageBase(toCopy) {
            type = toCopy.type;
            sourceEntropy = toCopy.sourceEntropy;
            deltaEntropy = toCopy.deltaEntropy;
            historyEntropy = toCopy.historyEntropy;
            sourceId = toCopy.sourceId;
            targetId = toCopy.targetId;
            sessionId = toCopy.sessionId;
            entropyId = toCopy.entropyId;
        };

        WifiMessageEntropy& operator=(const WifiMessageEntropy& toCopy) {
            WifiMessageBase::operator=(toCopy);
            type = toCopy.type;
            sourceEntropy = toCopy.sourceEntropy;
            deltaEntropy = toCopy.deltaEntropy;
            historyEntropy = toCopy.historyEntropy;
            sourceId = toCopy.sourceId;
            targetId = toCopy.targetId;
            sessionId = toCopy.sessionId;
            entropyId = toCopy.entropyId;
            return *this;
        };

        virtual WifiMessageBase* Clone() { return new WifiMessageEntropy(*this); }; 
    public:
        MessageType type;
        float sourceEntropy;
        float deltaEntropy;
        float historyEntropy;
        unsigned int sourceId;
        unsigned int targetId;
        unsigned int sessionId;
        unsigned int entropyId;
};
#endif

class RobotAntiEntropy:public RobotBase
{
    private:
        float entropy;
        vector<NeighborNode> neighborList;
        unsigned int entropyId;
        bool isSource;
        unsigned int zeroCount;
        unsigned int lastTime;
    
    public:
        RobotAntiEntropy(Model* model);
        ~RobotAntiEntropy();

        virtual void Estimate();
        virtual void MessageReceive(WifiMessageBase* mesg);
    private:
        void BroadCast();
        void RemoveDeadNeighbor();
        void ExchangeEntropy(unsigned int neighborId);
        int RandomSelectNeighbor();
        void SendAckMessage(unsigned int sourceId, float deltaEntropy, unsigned int sessionId);
        void UpdateEntropyList(unsigned int id, float deltaEntropy = 0);
        float GetLastEntropy(unsigned int id);
        void SetSession(unsigned int id, int session);
        int GetSession(unsigned int id);
        float GetHistoryEntropy(unsigned int id);
        void SetHistoryEntropy(unsigned int id, float entropy);
        void SetLastEntropy(unsigned int id, float entropy);
};

#ifndef __CONSTANT__
#define __CONSTANT__
const int MAX_UPDATE_TIME = 20;
const unsigned int SOURCE_NODE = 4;
const unsigned int MSG_ID_LENGTH = 10000;
const int SESSION_OPEN = 1;
const int SESSION_CLOSED = 0;
const int SESSION_UNCLOSED = 2;
#endif

#endif
